package com.weixing.mall.provider.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.weixing.mall.base.constant.DatePattern;
import com.weixing.mall.base.constant.GlobalConstant;
import com.weixing.mall.base.enums.IdGenTagEnum;
import com.weixing.mall.base.enums.WhetherEnum;
import com.weixing.mall.base.exception.BusinessException;
import com.weixing.mall.base.wrapper.Result;
import com.weixing.mall.base.wrapper.ResultUtil;
import com.weixing.mall.core.enums.OrderAppTagEnum;
import com.weixing.mall.core.enums.OrderSysTagEnum;
import com.weixing.mall.core.support.auth.MemAuth;
import com.weixing.mall.core.support.auth.SysAuth;
import com.weixing.mall.core.utils.EnvUtil;
import com.weixing.mall.leaf.api.service.IdGenServiceRpc;
import com.weixing.mall.provider.api.model.dto.DeliveryAddrDto;
import com.weixing.mall.provider.api.model.enums.ActTypeEnum;
import com.weixing.mall.provider.api.model.enums.AgentLevelEnum;
import com.weixing.mall.provider.api.model.enums.OrderTypeEnum;
import com.weixing.mall.provider.api.model.vo.ActGoodsVo;
import com.weixing.mall.provider.api.model.vo.ActRpcVo;
import com.weixing.mall.provider.api.model.vo.AgentRpcVo;
import com.weixing.mall.provider.api.model.vo.ItemVo;
import com.weixing.mall.provider.api.service.*;
import com.weixing.mall.provider.manager.AgentManager;
import com.weixing.mall.provider.manager.ProfitManager;
import com.weixing.mall.provider.model.bo.ItemBo;
import com.weixing.mall.provider.model.domain.Order;
import com.weixing.mall.provider.model.domain.OrderAgent;
import com.weixing.mall.provider.model.domain.OrderExpress;
import com.weixing.mall.provider.model.domain.OrderGoods;
import com.weixing.mall.provider.model.dto.*;
import com.weixing.mall.provider.model.enums.*;
import com.weixing.mall.provider.model.vo.PreOrderInfoVo;
import com.weixing.mall.provider.service.*;
import com.weixing.mall.provider.support.mq.OrderDivStockRedissonQueueProducer;
import com.weixing.mall.provider.support.mq.OrderPayEndRedissonQueueProducer;
import com.weixing.mall.provider.util.OrderCodeUtil;
import com.weixing.mall.provider.util.OrderUtil;
import com.weixing.mall.redis.RedisKeyConst;
import com.weixing.mall.redis.order.OrderDivStock;
import com.weixing.mall.redis.order.OrderPayEnd;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 订单模块-主订单 服务实现类
 * </p>
 *
 * @author Small
 * @since 2020-01-15
 */
@Slf4j
@Service
public class OrderTradeServiceImpl implements IOrderTradeService {
    @Autowired
    private IdGenServiceRpc idGenServiceRpc;
    @Autowired
    private IOrderService orderService;
    @Autowired
    private IOrderExpressService orderExpressService;
    @Autowired
    private IOrderGoodsService orderGoodsService;
    @Autowired
    private CartFeign cartFeign;
    @Autowired
    private ItemFeign itemFeign;
    @Autowired
    private ActivityGoodsRpcService activityGoodsRpcService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private AgentDeliveryServiceRpc agentDeliveryServiceRpc;
    @Autowired
    private MemberServiceRpc memberServiceRpc;
    @Autowired
    private ProfitManager profitManager;
    @Autowired
    private IOrderAgentService orderAgentService;
    @Autowired
    private AgentManager agentManager;
    @Autowired
    private OrderPayEndRedissonQueueProducer orderPayEndRedissonQueueProducer;
    @Autowired
    private OrderDivStockRedissonQueueProducer orderDivStockRedissonQueueProducer;

    /**
     * 方法描述: 会员下单：立即购买
     * @Author Small
     * @param orderDto
     * @param memAuth
     * @param agentRpcVo
     * @Date 2020/1/15 11:56
     * @return java.lang.Long
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result memberPreOrderOfQuick(MemberPreOrderDto orderDto, MemAuth memAuth, AgentRpcVo agentRpcVo) {

        // 查看商品是否参加活动，如果是活动商品则锁定库存并减库存
        Long itemId = orderDto.getGoods().getProductId();
        PreOrderInfoVo preOrderInfoVo = new PreOrderInfoVo();
        try {
            Result<ItemBo> itemBoResult = loadItemPo(null, itemId);
            // 商品信息
            if (!itemBoResult.isSuccess()) {
                return itemBoResult;
            }
            ItemBo itemPo = itemBoResult.getData();
            ItemVo itemVo = itemPo.getItemVo();
            // 生成主订单
            Order order = createMemberOrder(memAuth, agentRpcVo, itemPo, orderDto.getExpressName(), orderDto.getRemark());
            //添加订单商品信息
            OrderGoods orderGoods = createOrderGoods(itemVo, order, orderDto.getWeight(), orderDto.getHeight());
            //添加订单收货信息
            OrderExpress orderExpress = createOrderExpress(orderDto.getShipAddr(), order.getId(), orderDto.getExpressType());

            preOrderInfoVo.setTradeId(order.getId());
            String money = NumberUtil.decimalFormatMoney(order.getActualPrice().doubleValue());
            preOrderInfoVo.setOrderTotalAmount(money);
            preOrderInfoVo.setOutTradeNo(order.getOutTradeNo());
            preOrderInfoVo.setIdentificationCode(order.getIdentificationCode());
            orderService.save(order);
            orderExpressService.save(orderExpress);
            orderGoodsService.save(orderGoods);
            // 计算代理获利
            List<OrderAgent> orderAgents = profitManager.calcProfit(order, agentRpcVo, null);
            if (CollUtil.isNotEmpty(orderAgents)) {
                orderAgentService.saveBatch(orderAgents);
            }

            // 下单送积分
            memberServiceRpc.bonusPointsHandle(memAuth.getMid(), null, order.getOrderPrice(), null);
            // 订单支付时间倒计时
            orderPayEndRedissonQueueProducer.producer(new OrderPayEnd(order.getId(), orderGoods.getProductId()));
            // 更新代理交易日期
            agentManager.updateAgentTradeDate(agentRpcVo);
        } catch (Exception e) {
            log.warn("客户立即下单操作发生异常：", e);
            throw new BusinessException("下单失败！");
        }

        return ResultUtil.success(preOrderInfoVo);
    }


    /**
     * 方法描述: 会员购物车结算
     * @Author Small
     * @param
     * @param orderDto
     * @param memAuth
     * @param agentRpcVo
     * @Date 2020/1/15 18:46
     * @return void
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public PreOrderInfoVo memberPreOrderOfCart(MemberPreOrderCartDto orderDto, MemAuth memAuth, AgentRpcVo agentRpcVo) {
        // 加载购物车选中商品
        Result<List<ItemVo>> searchItemResult = cartFeign.loadSelectedItem(memAuth.getMid());
        if (!searchItemResult.isSuccess()) {
            throw new BusinessException(searchItemResult.getMsg());
        }
        List<ItemVo> items = searchItemResult.getData();
        if (CollUtil.isEmpty(items)) {
            throw new BusinessException("请至少选中一件商品");
        } else if (items.size() > 1) {
            throw new BusinessException("只能选一件商品");
        }
        // 购物车商品
        List<Long> cartItemIds = Lists.newArrayList();
        ItemVo vo = items.get(0);
        cartItemIds.add(vo.getId());

        ItemBo itemPo = new ItemBo(vo, null, false);
        // 订单
        Order order = createMemberOrder(memAuth, agentRpcVo, itemPo, orderDto.getExpressName(), orderDto.getRemark());
        // 订单关联商品
        OrderGoods orderGoods = createOrderGoods(vo, order, orderDto.getWeight(), orderDto.getHeight());
        // 订单收货地址
        OrderExpress orderExpress = createOrderExpress(orderDto.getShipAddr(), order.getId(), vo.getExpressType());

        orderService.save(order);
        orderExpressService.save(orderExpress);
        orderGoodsService.save(orderGoods);
        // 移除已购买的购物车商品
        cartFeign.removeItemFromCart(cartItemIds);
        // 计算代理获利
        List<OrderAgent> orderAgents = profitManager.calcProfit(order, agentRpcVo, null);
        if (CollUtil.isNotEmpty(orderAgents)) {
            orderAgentService.saveBatch(orderAgents);
        }
        // 下单送积分
        memberServiceRpc.bonusPointsHandle(memAuth.getMid(), null, order.getOrderPrice(), null);
        // 更新代理交易日期
        agentManager.updateAgentTradeDate(agentRpcVo);
        PreOrderInfoVo preOrderInfoVo = new PreOrderInfoVo();
        preOrderInfoVo.setTradeId(order.getId());
        preOrderInfoVo.setIdentificationCode(order.getIdentificationCode());
        preOrderInfoVo.setOutTradeNo(order.getOutTradeNo());
        preOrderInfoVo.setOrderTotalAmount(NumberUtil.decimalFormatMoney(order.getActualPrice().doubleValue()));
        return preOrderInfoVo;
    }

    /**
     * 方法描述: 秒杀
     * @Author Small
     * @param orderDto
     * @param memAuth
     * @param agentRpcVo
     * @Date 2020/4/26 14:35
     * @return com.weixing.mall.base.wrapper.Result<com.weixing.mall.provider.model.vo.PreOrderInfoVo>
     */
    @Override
    public Result seckill(MemberSeckillDto orderDto, MemAuth memAuth, AgentRpcVo agentRpcVo) {
        // 查看商品是否参加活动，如果是活动商品则锁定库存并减库存
        Long actId = orderDto.getActId();
        Long itemId = orderDto.getGoods().getProductId();
        String rediskey = StrUtil.format(RedisKeyConst.ACT_ITEM_STOCK, actId == null ? null : actId.longValue(), itemId == null ? null : itemId.longValue());
        String keyEx = "";
        if (null != actId) {
            Object itemObj = redisTemplate.opsForValue().get(rediskey);
            if (null == itemObj) {
                return ResultUtil.error("活动尚未发布或者已结束");
            }
            int itemStock = (int) itemObj;
            if (itemStock < 1) {
                return ResultUtil.error("商品库存不足");
            }
            Long increment = redisTemplate.opsForValue().increment(rediskey, -1);
            if (increment < 0) {
                // 库存不足，需要增加刚刚减去的库存
                redisTemplate.opsForValue().increment(rediskey, 1);
                return ResultUtil.error("商品库存不足");
            }
        } else {
            return ResultUtil.error("参数不合法");
        }
        PreOrderInfoVo preOrderInfoVo = new PreOrderInfoVo();
        try {
            Result<ItemBo> itemBoResult = loadItemPo(actId, itemId);
            // 商品信息
            if (!itemBoResult.isSuccess()) {
                throw new BusinessException(itemBoResult.getMsg());
            }
            ItemBo itemPo = itemBoResult.getData();
            ItemVo itemVo = itemPo.getItemVo();

            Order order = createMemberOrder(memAuth, agentRpcVo, itemPo, orderDto.getExpressName(), orderDto.getRemark());
            //添加订单商品信息
            OrderGoods orderGoods = createOrderGoods(itemVo, order, orderDto.getWeight(), orderDto.getHeight());
            //添加订单收货信息
            OrderExpress orderExpress = createOrderExpress(orderDto.getShipAddr(), order.getId(), orderDto.getExpressType());

            preOrderInfoVo.setTradeId(order.getId());
            String money = NumberUtil.decimalFormatMoney(order.getActualPrice().doubleValue());
            preOrderInfoVo.setOrderTotalAmount(money);
            preOrderInfoVo.setIdentificationCode(order.getIdentificationCode());
            preOrderInfoVo.setOutTradeNo(order.getOutTradeNo());
            orderService.save(order);
            orderExpressService.save(orderExpress);
            orderGoodsService.save(orderGoods);
            // 计算代理获利
            List<OrderAgent> orderAgents = profitManager.calcProfit(order, agentRpcVo, itemPo.getActRpcVo().getRebateRule());
            if (CollUtil.isNotEmpty(orderAgents)) {
                orderAgentService.saveBatch(orderAgents);
            }
            // 数据库真正扣减库存
            orderDivStockRedissonQueueProducer.producer(new OrderDivStock(order.getId(), itemId, actId, 1));
            // 下单送积分
            memberServiceRpc.bonusPointsHandle(memAuth.getMid(), null, order.getOrderPrice(), null);
            // 订单支付时间倒计时
            orderPayEndRedissonQueueProducer.producer(new OrderPayEnd(order.getId(), orderGoods.getProductId()));

        } catch (Exception e) {
            log.warn("客户秒杀操作发生异常：", e);
            // 如果下单过程中发生异常，则回滚库存
            redisTemplate.opsForValue().increment(rediskey, 1);
            redisTemplate.delete(keyEx);
            throw new BusinessException("下单失败");
        }

        return ResultUtil.success(preOrderInfoVo);
    }

    @Override
    public void updateOrderGoods(Long orderId, Long itemId) {
        OrderGoods orderGoods = orderGoodsService.getByOrderId(orderId);
        Result<ItemBo> itemBoResult = loadItemPo(null, itemId);
        if (!itemBoResult.isSuccess()) {
            throw new BusinessException(itemBoResult.getMsg());
        }
        ItemBo data = itemBoResult.getData();
        ItemVo itemVo = data.getItemVo();
        orderGoods.setProductSn(itemVo.getProductSn());
        orderGoods.setProductId(itemVo.getProductId());
        orderGoods.setSize(itemVo.getSize());
        orderGoods.setColor(itemVo.getColor());
        orderGoods.setSkuDesp(itemVo.getProductSkuDesp());
        orderGoods.setGoodsImg(itemVo.getProductImg());
        orderGoods.setGoodsName(itemVo.getProductName());
        orderGoods.setPrice(itemVo.getDiscountPrice());
        orderGoods.setMarketPrice(itemVo.getMarketPrice());
        orderGoodsService.updateById(orderGoods);
    }

    /**
     * 修改订单颜色尺码，邮寄地址，身高体重
     * @param paramDto 修改参数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOrderParam(OrderParamDto paramDto) {
        Order order = orderService.getById(paramDto.getOrderId());
        if(StrUtil.isNotEmpty(paramDto.getExpressName()) || StrUtil.isNotEmpty(paramDto.getRemark())){
            order.setExpressName(paramDto.getExpressName());
            order.setRemark(paramDto.getRemark());
            orderService.updateById(order);
        }
        // 身高体重
        if (null != paramDto.getHeight() || null != paramDto.getWeight()) {
            QueryWrapper<OrderGoods> wrapper = new QueryWrapper<OrderGoods>().eq("order_id", paramDto.getOrderId());
            OrderGoods orderGoods = orderGoodsService.getOne(wrapper);
            orderGoods.setHeight(paramDto.getHeight());
            orderGoods.setWeight(paramDto.getWeight());
            orderGoodsService.updateById(orderGoods);
        }
        // 订单邮寄地址
        if (null != paramDto.getShipAddr()) {
            OrderExpress orderExpress = orderExpressService.findByOrderId(paramDto.getOrderId());
            BeanUtils.copyProperties(paramDto.getShipAddr(), orderExpress);
            orderExpressService.updateById(orderExpress);
        }
        // 颜色尺码
        if (null != paramDto.getProductId()){
            if (OrderTypeEnum.SECKILL.getValue().equals(order.getOrderType())){
                throw new BusinessException("秒杀订单不允许修改颜色尺码");
            }
            updateOrderGoods(paramDto.getOrderId(), paramDto.getProductId());
        }

    }


    /**
     * 方法描述: 代理下单
     *
     * @param orderDto
     * @param agent
     * @Date 2020/3/30 10:42
     * @return void
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result preOrderOfAgent(AgentPlaceOrderDto orderDto, AgentRpcVo agent) {
        // 查看商品是否参加活动，如果是活动商品则锁定库存并减库存
        Long actId = orderDto.getActId();
        Long itemId = orderDto.getItemId();

        String rediskey = StrUtil.format(RedisKeyConst.ACT_ITEM_STOCK, actId == null ? null : actId.longValue(), itemId == null ? null : itemId.longValue());
        if (null != actId) {
            Object itemObj = redisTemplate.opsForValue().get(rediskey);
            if (null == itemObj) {
                return ResultUtil.error("活动尚未发布或者已结束");
            }
            int itemStock = (int) itemObj;
            if (itemStock < 1) {
                return ResultUtil.error("商品库存不足");
            }
            Long increment = redisTemplate.opsForValue().increment(rediskey, -1);
            if (increment < 0) {
                // 库存不足，需要增加刚刚减去的库存
                redisTemplate.opsForValue().increment(rediskey, 1);
                return ResultUtil.error("商品库存不足");
            }
        }
        try {
            Result<ItemBo> itemBoResult = loadItemPo(actId, itemId);
            // 商品信息
            if (!itemBoResult.isSuccess()) {
                throw new BusinessException(itemBoResult.getMsg());
            }
            ItemBo itemPo = itemBoResult.getData();
            ItemVo itemVo = itemPo.getItemVo();
            // 生成主订单
            Order order = createAgentOrder(agent, itemPo, orderDto);
            // 订单邮寄地址信息
            OrderExpress orderExpress = createOrderExpress(orderDto.getShipAddr(), order.getId(), orderDto.getExpressType());
            // 如果地址为新地址则新增
//            if (null == orderDto.getShipAddr().getAddrId()) {
            DeliveryAddrDto addrDto = new DeliveryAddrDto();
            addrDto.setAgentId(agent.getId());
            addrDto.setAddrId(orderDto.getShipAddr().getAddrId());
            BeanUtils.copyProperties(orderDto.getShipAddr(), addrDto);
            agentDeliveryServiceRpc.createDelivery(addrDto);
//            }
            // 订单关联商品信息
            OrderGoods orderGoods = createOrderGoods(itemVo, order, orderDto.getWeight(), orderDto.getHeight());
            orderService.save(order);
            orderExpressService.save(orderExpress);
            orderGoodsService.save(orderGoods);
            // 数据库真正扣减库存
            if (null != actId) {
                orderDivStockRedissonQueueProducer.producer(new OrderDivStock(order.getId(), itemId, actId, 1));
            }
            // 计算代理获利
            Long discountRule = null == itemPo.getActRpcVo() ? null : itemPo.getActRpcVo().getDiscountRule();
            List<OrderAgent> orderAgents = profitManager.calcProfit(order, agent, discountRule);
            if (CollUtil.isNotEmpty(orderAgents)) {
                orderAgentService.saveBatch(orderAgents);
            }
            // 更新代理交易日期
            agentManager.updateAgentTradeDate(agent);
        } catch (Exception e) {
            log.warn("代理商下单操作发生异常：", e);
            if (null != actId) {
                // 如果下单过程中发生异常，则回滚库存
                redisTemplate.opsForValue().increment(rediskey, 1);
            }
            throw new BusinessException("代理商下单操作发生异常");
        }
        return ResultUtil.success();
    }


    /**
     * 方法描述: 客服下单
     * @Author Small
     * @param placeOrderDto
     * @param sysAuth
     * @Date 2020/4/1 9:01
     * @return void
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result kefuPlaceOrder(KefuPlaceOrderDto placeOrderDto, SysAuth sysAuth) {

        // 查看商品是否参加活动，如果是活动商品则锁定库存并减库存
        Long actId = placeOrderDto.getActId();
        Long itemId = placeOrderDto.getProductId();

        String rediskey = StrUtil.format(RedisKeyConst.ACT_ITEM_STOCK, actId == null ? null : actId.longValue(), itemId == null ? null : itemId.longValue());
        if (null != actId) {
            Object itemObj = redisTemplate.opsForValue().get(rediskey);
            if (null == itemObj) {
                return ResultUtil.error("活动尚未发布或者已结束");
            }
            int itemStock = (int) itemObj;
            if (itemStock < 1) {
                return ResultUtil.error("商品库存不足");
            }
            Long increment = redisTemplate.opsForValue().increment(rediskey, -1);
            if (increment < 0) {
                // 库存不足，需要增加刚刚减去的库存
                redisTemplate.opsForValue().increment(rediskey, 1);
                return ResultUtil.error("商品库存不足");
            }
        }
        try {
            Result<ItemBo> itemBoResult = loadItemPo(actId, itemId);
            // 商品信息
            if (!itemBoResult.isSuccess()) {
                return itemBoResult;
            }
            ItemBo itemBo = itemBoResult.getData();
            ItemVo itemVo = itemBo.getItemVo();
            // 生成主订单
            Order order = createKefuOrder(placeOrderDto, itemBo, sysAuth);
            // 订单邮寄地址信息
            OrderExpress orderExpress = createOrderExpress(placeOrderDto.getAddress(), order.getId(), placeOrderDto.getExpressType());
            // 订单关联商品信息
            OrderGoods orderGoods = createOrderGoods(itemVo, order, placeOrderDto.getWeight(), placeOrderDto.getHeight());
            orderService.save(order);
            orderExpressService.save(orderExpress);
            orderGoodsService.save(orderGoods);
            List<OrderAgent> orderAgents = profitManager.calcProfit(order, null, null);
            if (CollUtil.isNotEmpty(orderAgents)) {
                orderAgentService.saveBatch(orderAgents);
            }
            // 数据库真正扣减库存
            if (null != actId) {
                String divKey = StrUtil.format(RedisKeyConst.ACT_ITEM_DIVIDE_STOCK_FMT, actId.longValue(), itemId.longValue());
                String cnt = String.valueOf(1);
                stringRedisTemplate.opsForList().leftPush(divKey, cnt);
            }
        } catch (Exception e) {
            log.warn("客服下单操作发生异常：", e);
            if (null != actId) {
                // 如果下单过程中发生异常，则回滚库存
                redisTemplate.opsForValue().increment(rediskey, 1);
            }
        }
        return ResultUtil.success();
    }


    /**
     * 方法描述: 客服订单
     * @Author Small
     * @param placeOrderDto
     * @param itemBo
     * @param sysAuth
     * @Date 2020/4/10 19:28
     * @return com.weixing.mall.provider.model.domain.Order
     */
    private Order createKefuOrder(KefuPlaceOrderDto placeOrderDto, ItemBo itemBo, SysAuth sysAuth) {
        Order order = new Order();
        long orderId = getOrderId();
        order.setId(orderId);
        order.setIdentificationCode(OrderCodeUtil.toSerialCode(orderId));
        // 订单下单人
        order.setBuyerId(sysAuth.getUid());
        order.setBuyer(sysAuth.getRealName());
        order.setOrderFrom(OrderFromEnum.CUSTOMER.getValue());
        // 订单状态
        order.setOrderStatus(OrderStateEnum.HAS_PAY.getValue());
        order.setFrontOrderStatus(OrderFrontStateEnum.WAIT_SHIP.getValue());
        order.setIsPay(WhetherEnum.YES.getValue());
        // 订单价格
        order.setOrderPrice(itemBo.getItemVo().getDiscountPrice());
        order.setActualPrice(itemBo.getItemVo().getDiscountPrice());
        order.setMarketPrice(itemBo.getItemVo().getMarketPrice());
        // 订单审核信息
        order.setAuditor(sysAuth.getUid());
        order.setAuditDept(AuditDeptEnum.SERVICE_DEPT.getValue());
        order.setAuditStatus(OrderAuditStateEnum.AGENT_AUDIT_SUCCESS.getValue());
        // 订单所属客服
        order.setCustomerId(sysAuth.getUid());
        order.setCustomerName(sysAuth.getRealName());
        //备注
        order.setRemark(placeOrderDto.getRemark());
        // 订单类型
        Long actId = placeOrderDto.getActId();
        if (itemBo.isActItem()) {
            ActRpcVo actRpcVo = itemBo.getActRpcVo();
            order.setActId(actId);
            order.setActName(actRpcVo.getActName());
            ActTypeEnum actType = actRpcVo.getActType();
            if (ActTypeEnum.ACT_SECKILL == actType) {
                order.setOrderSn(genOrderSn(GlobalConstant.ORDER_PRE_MS));
                order.setOrderType(OrderTypeEnum.SECKILL.getValue());
            } else {
                order.setOrderSn(genOrderSn(GlobalConstant.ORDER_PRE_DL));
                order.setOrderType(OrderTypeEnum.AGENT.getValue());
            }
        } else {
            order.setOrderSn(genOrderSn(GlobalConstant.ORDER_PRE_ZJ));
            order.setOrderType(OrderTypeEnum.NORMAL.getValue());
        }
        return order;
    }


    /**
     * 方法描述: 代理商下单生成订单
     *
     * @param agent        代理商
     * @param itemBo
     * @param orderDto
     * @Date 2020/3/29 16:30
     * @return Order
     */
    private Order createAgentOrder(AgentRpcVo agent, ItemBo itemBo, AgentPlaceOrderDto orderDto) {
        Order order = new Order();
        long orderId = getOrderId();
        order.setId(orderId);
        order.setIdentificationCode(OrderCodeUtil.toSerialCode(orderId));
        // 购买人信息
        order.setBuyerId(agent.getId());
        order.setBuyer(agent.getAgentName());
        order.setOrderFrom(OrderFromEnum.AGENT.getValue());
        // 代理商信息
        order.setAgentId(agent.getId());
        order.setAgentSn(agent.getAgentSn());
        order.setAgentName(agent.getAgentName());

        order.setOrderStatus(OrderStateEnum.HAS_PAY.getValue());
        order.setFrontOrderStatus(OrderFrontStateEnum.ALL.getValue());
        order.setSysTag(OrderSysTagEnum.YFK_TAG_103.getValue());
        order.setAppTag(OrderAppTagEnum.YFK_TAG_101.getValue());
        order.setOrderPrice(itemBo.getItemVo().getDiscountPrice());
        order.setActualPrice(itemBo.getItemVo().getDiscountPrice());
        order.setMarketPrice(itemBo.getItemVo().getMarketPrice());
        order.setIsPay(WhetherEnum.YES.getValue());
        order.setExpressName(orderDto.getExpressName());
        order.setRemark(orderDto.getRemark());
        // 代理商审核信息
        order.setAuditDept(AuditDeptEnum.AGENT.getValue());
        order.setAuditor(agent.getId());
        order.setAgentCliamLine(agent.getAgentTreePath());
        order.setAuditStatus(OrderAuditStateEnum.AGENT_WAIT_AUDIT.getValue());

        // 订单所属客服信息（代理商和客户的客服是一致的）
        order.setCustomerId(agent.getCustomerId());
        order.setCustomerName(agent.getCustomerName());
        // 订单所属经销商
        OrderUtil.doOrderAgentClaim(order);
        // 订单所属经销商
        if (null != order.getDistributorId() && 0 != order.getDistributorId()) {
            List<AgentRpcVo> treeList = agent.getTreeList();
            int size = treeList.size();
            AgentRpcVo agentRpcVo1 = treeList.get(size - 1);
            if (AgentLevelEnum.DEALER.getValue().equals(agentRpcVo1.getAgentLevel())) {
                order.setDistributorName(agentRpcVo1.getAgentName());
            }
        }
        // 订单分类
        Long actId = orderDto.getActId();

        if (itemBo.isActItem()) {
            order.setOrderSn(genOrderSn(GlobalConstant.ORDER_PRE_DL));
            ActRpcVo actRpcVo = itemBo.getActRpcVo();
            order.setActId(actId);
            order.setActName(actRpcVo.getActName());
            ActTypeEnum actType = actRpcVo.getActType();
            if (ActTypeEnum.ACT_SECKILL == actType) {
                throw new BusinessException("您不能以代理商角色下秒杀活动订单");
            } else {
                order.setOrderType(OrderTypeEnum.AGENT.getValue());
            }
        } else {
            order.setOrderSn(genOrderSn(GlobalConstant.ORDER_PRE_ZJ));
            order.setOrderType(OrderTypeEnum.NORMAL.getValue());
        }
        return order;
    }

    /**
     * 查询商品信息
     *
     * @param actId
     * @param itemId
     * @return
     */
    private Result<ItemBo> loadItemPo(Long actId, Long itemId) {
        ItemBo itemPo = null;
        if (null != actId) {
            Result<ActGoodsVo> actGoodsVoResult = activityGoodsRpcService.selectByActIdAndItemId(itemId, actId);
            ActGoodsVo actGoodsVo = actGoodsVoResult.getData();
            if (!actGoodsVoResult.isSuccess()) {
                return ResultUtil.error(actGoodsVoResult.getMsg());
            }
            if (null == actGoodsVo) {
                return ResultUtil.error("商品不存在或已下架");
            }
            ItemVo itemVo = new ItemVo();
            itemVo.setId(actGoodsVo.getId());
            itemVo.setGoodsId(actGoodsVo.getGoodsId());
            itemVo.setGoodsSn(actGoodsVo.getGoodsSn());
            itemVo.setStyleNo(actGoodsVo.getStyleNo());
            itemVo.setProductId(actGoodsVo.getProductId());
            itemVo.setProductName(actGoodsVo.getProductName());
            // 这个皮球踢的好，我TMD服了，系统烂是有原因的
            Result<ItemVo> itemVoResult = getItem(itemId);
            if (!itemVoResult.isSuccess()) {
                throw new BusinessException("下单失败");
            } else {
                itemVo.setProductSn(itemVoResult.getData().getProductSn());
            }
            itemVo.setProductImg(actGoodsVo.getProductImg());
            itemVo.setStock(actGoodsVo.getProductCount());
            itemVo.setDiscountPrice(actGoodsVo.getActPrice());
            itemVo.setMarketPrice(actGoodsVo.getProductPrice());
            itemVo.setProductSku(actGoodsVo.getProductSku());
            itemVo.setProductSkuDesp(actGoodsVo.getProductSkuDesp());
            itemVo.setProductStock(actGoodsVo.getProductCount());
            itemVo.setSupplierName(actGoodsVo.getSupplierName());
            itemVo.setCatId(actGoodsVo.getCatId());
            itemVo.setCatName(actGoodsVo.getCatName());
            String[] skuDesp = actGoodsVo.getProductSkuDesp().split(",");
            if (skuDesp.length == 2) {
                itemVo.setColor(StrUtil.subBetween(actGoodsVo.getProductSkuDesp(), ":", ","));
                itemVo.setSize(StrUtil.subAfter(actGoodsVo.getProductSkuDesp(), ":", true));
            }
            itemPo = new ItemBo(itemVo, actGoodsVo.getActRpcVo(), true);
        } else {
            Result<ItemVo> itemVoResult = getItem(itemId);
            if (!itemVoResult.isSuccess()) {
                return ResultUtil.error(itemVoResult.getMsg());
            }
            ItemVo data = itemVoResult.getData();
            if (null == data){
                return ResultUtil.error("商品不存在或已下架");
            }
            if (2 != data.getGoodsState().intValue()) {
                return ResultUtil.error("商品已下架");
            }
            itemPo = new ItemBo(data, null, false);
        }
        return ResultUtil.success(itemPo);
    }


    private Result<ItemVo> getItem(Long itemId) {
        Result<ItemVo> itemResult = itemFeign.findById(itemId);
        ItemVo itemVo = itemResult.getData();
        if (!itemResult.isSuccess()) {
            return ResultUtil.error(itemResult.getMsg());
        } else {
            if (null == itemVo) {
                return ResultUtil.error("商品不存在");
            }
        }
        return ResultUtil.success(itemVo);
    }

    /**
     * 创建会员订单
     *
     * @param memAuth   会员
     * @param agentRpcVo 代理信息
     * @param itemBo  商品信息
     * @param expressName  快递信息
     * @param remark  备注
     * @return  Order
     */
    private Order createMemberOrder(MemAuth memAuth, AgentRpcVo agentRpcVo, ItemBo itemBo, String expressName, String remark) {
        Order order = new Order();
        long orderId = getOrderId();
        order.setId(orderId);
        order.setIdentificationCode(OrderCodeUtil.toSerialCode(orderId));
        order.setIsPay(WhetherEnum.NO.getValue());
        order.setBuyerId(memAuth.getMid());
        order.setBuyer(memAuth.getMm());
        order.setOrderFrom(OrderFromEnum.MEMBER.getValue());
        order.setOrderStatus(OrderStateEnum.WAIT_PAY.getValue());
        order.setFrontOrderStatus(OrderFrontStateEnum.WAIT_PAY.getValue());
        order.setSysTag(OrderSysTagEnum.DFK_TAG_101.getValue());
        order.setExpressName(expressName);
        order.setRemark(remark);
        ItemVo itemVo = itemBo.getItemVo();
        order.setOrderPrice(itemVo.getDiscountPrice());
        order.setActualPrice(itemVo.getDiscountPrice());
        order.setMarketPrice(itemVo.getMarketPrice());
        if (null == itemBo.getActRpcVo()) {
            order.setOrderSn(genOrderSn(GlobalConstant.ORDER_PRE_ZJ));
            // 购物车订单都是正价订单
            order.setOrderType(OrderTypeEnum.NORMAL.getValue());
        } else {
            order.setOrderSn(genOrderSn(GlobalConstant.ORDER_PRE_MS));
            // 秒杀订单无需绑定代理商和客服
            ActRpcVo actRpcVo = itemBo.getActRpcVo();
            order.setActId(actRpcVo.getId());
            order.setActName(actRpcVo.getActName());
            ActTypeEnum actType = actRpcVo.getActType();
            if (ActTypeEnum.ACT_AGENT == actType) {
                throw new BusinessException("您不能下代理商活动订单");
            } else {
                order.setOrderType(OrderTypeEnum.SECKILL.getValue());
            }
        }
        // 绑定代理信息
        if (null != agentRpcVo) {
            order.setAgentId(agentRpcVo.getId());
            order.setAgentSn(agentRpcVo.getAgentSn());
            order.setAgentName(agentRpcVo.getAgentName());
            order.setAgentCliamLine(agentRpcVo.getAgentTreePath());
            order.setCustomerId(agentRpcVo.getCustomerId());
            order.setCustomerName(agentRpcVo.getCustomerName());
            // 审核人信息
            order.setAuditor(agentRpcVo.getId());
            order.setAuditDept(AuditDeptEnum.AGENT.getValue());
            OrderUtil.doOrderAgentClaim(order);
        } else {
            if (null != memAuth.getKid()) {
                order.setCustomerId(memAuth.getKid());
                order.setCustomerName(memAuth.getKn());
                order.setAuditor(memAuth.getKid());
                order.setAuditDept(AuditDeptEnum.SERVICE_DEPT.getValue());
            }
        }
        OrderUtil.doOrderAgentClaim(order);
        // 订单所属经销商
        if (null != order.getDistributorId() && 0 != order.getDistributorId()){
            List<AgentRpcVo> treeList = agentRpcVo.getTreeList();
            int size = treeList.size();
            AgentRpcVo agentRpcVo1 = treeList.get(size - 1);
            if (AgentLevelEnum.DEALER.getValue().equals(agentRpcVo1.getAgentLevel())){
                order.setDistributorName(agentRpcVo1.getAgentName());
            }
        }
        order.setPayEndTime(DateUtil.offsetMinute(new Date(), EnvUtil.isDev() ? 2 : 15));
        return order;
    }

    private long getOrderId() {
        long id = idGenServiceRpc.segmentKey(IdGenTagEnum.ORDER_ID.getValue());
        if (id == 0) {
            throw new BusinessException("下单失败！");
        }
        return id;
    }


    /**
     * 方法描述: 创建订单关联商品表
     * @Author Small
     * @param itemVo
     * @param order
     * @param weight
     * @param height
     * @Date 2020/4/22 17:06
     * @return OrderGoods
     */
    private OrderGoods createOrderGoods(ItemVo itemVo, Order order, Double weight, Double height) {
        OrderGoods orderGoods = new OrderGoods();
        orderGoods.setOrderId(order.getId());
        orderGoods.setProductId(itemVo.getProductId());
        orderGoods.setGoodsId(itemVo.getGoodsId());
        orderGoods.setQuantity(1);
        orderGoods.setPrice(itemVo.getDiscountPrice());
        orderGoods.setHeight(height);
        orderGoods.setWeight(weight);
        orderGoods.setGoodsImg(itemVo.getProductImg());
        orderGoods.setSkuDesp(itemVo.getProductSkuDesp());
        orderGoods.setGoodsName(itemVo.getProductName());
        orderGoods.setGoodsSn(itemVo.getGoodsSn());
        orderGoods.setStyleNo(itemVo.getStyleNo());
        orderGoods.setProductSn(itemVo.getProductSn());
        orderGoods.setMarketPrice(itemVo.getMarketPrice());
        orderGoods.setSupplierName(itemVo.getSupplierName());
        orderGoods.setColor(itemVo.getColor());
        orderGoods.setSize(itemVo.getSize());
        orderGoods.setCatId(itemVo.getCatId());
        orderGoods.setCatName(itemVo.getCatName());
        return orderGoods;
    }

    /**
     * 方法描述: 创建订单配送记录信息
     * @Author Small
     * @param shipAddrDto 收货地址
     * @param orderId  主订单id
     * @Date 2020/2/3 15:45
     * @return void
     */
    private OrderExpress createOrderExpress(ShipAddrDto shipAddrDto, Long orderId, Integer expressType) {
        OrderExpress orderExpress = new OrderExpress();
        orderExpress.setOrderId(orderId);
        BeanUtils.copyProperties(shipAddrDto, orderExpress);
        orderExpress.setExpressType(expressType);
        return orderExpress;
    }


    /**
     * 方法描述:  订单自增序列号
     * @Author Small
     * @param prefix 订单前缀
     * @Date 2020/5/15 14:23
     * @return java.lang.Long
     */
    public String genOrderSn(String prefix) {
        long liveTime = 86400L;
        String dateFmt = DateUtil.format(new Date(), DatePattern.PURE_DATE_PATTERN);
        String key = IdGenTagEnum.ORDER_SN_REDIS.getValue() + dateFmt;
        RedisAtomicLong entityIdCounter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
        Long increment = entityIdCounter.getAndIncrement();
        //初始设置过期时间
        if ((null == increment || increment.longValue() == 0) && liveTime > 0) {
            entityIdCounter.expire(liveTime, TimeUnit.SECONDS);
        }
        return OrderUtil.genSubOrderSn(prefix, dateFmt, increment + 1);
    }
}
